//---------------------------------------------------------------------------

#include "vcl_stl.h"
#pragma hdrstop

#include "h_tea.h"

//---------------------------------------------------------------------------
#define Bkhtonl(x) BkSwapInt(x)
#define Bkntohl(x) BkSwapInt(x)

typedef unsigned int BK_UINT32;

static int BkSwapInt(int n);
static void TeaEncrypt64Bits(BK_UINT32 *v, const BK_UINT32 *k);
static void TeaDecrypt64Bits(BK_UINT32 *v, const BK_UINT32 *k);

static int BkSwapInt(int n)
{
   long r;
   char *s1, *s2;

   s1 = (char*)&n + 3;
   s2 = (char*)&r;
   *s2++ = *s1--;
   *s2++ = *s1--;
   *s2++ = *s1--;
   *s2++ = *s1--;
   return r;
}

static void TeaEncrypt64Bits(BK_UINT32 *v, const BK_UINT32 *k)
{
   BK_UINT32 y, z, sum, delta, a, b, c, d;
   int n;

   sum   = 0;
   delta = 0x9e3779b9UL;
   y     = Bkntohl(v[0]);
   z     = Bkntohl(v[1]);
   a     = Bkntohl(k[0]);
   b     = Bkntohl(k[1]);
   c     = Bkntohl(k[2]);
   d     = Bkntohl(k[3]);

   for(n = 32; n > 0; n--){
      sum += delta;
      y += (z << 4) + (a ^ z) + (sum ^ (z >> 5)) + b;
      z += (y << 4) + (c ^ y) + (sum ^ (y >> 5)) + d;
   }

   v[0] = Bkhtonl(y);
   v[1] = Bkhtonl(z);
}

static void TeaDecrypt64Bits(BK_UINT32 *v, const BK_UINT32 *k)
{
   BK_UINT32 y, z, sum, delta, a, b, c, d;
   int n;

   sum   = 0xc6ef3720UL;
   delta = 0x9e3779b9UL;
   y     = Bkntohl(v[0]);
   z     = Bkntohl(v[1]);
   a     = Bkntohl(k[0]);
   b     = Bkntohl(k[1]);
   c     = Bkntohl(k[2]);
   d     = Bkntohl(k[3]);

   for(n = 32; n > 0; n--){
      z -= (y << 4) + (c ^ y) + (sum ^ (y >> 5)) + d;
      y -= (z << 4) + (a ^ z) + (sum ^ (z >> 5)) + b;
      sum -= delta;
   }

   v[0] = Bkhtonl(y);
   v[1] = Bkhtonl(z);
}

void BkTeaEncrypt(void *buf, const void *key, int len)
{
   BK_UINT32 k[4], v[2];
   char *p;
   int i;

   p = (char*)buf;
   memcpy(k, key, 16);

   for(i = len / 8; i > 0; i--){
      memcpy(v, p, 8);
      TeaEncrypt64Bits(v, k);
      memcpy(p, v, 8);
      p += 8;
   }
}

void BkTeaDecrypt(void *buf, const void *key, int len)
{
   BK_UINT32 k[4], v[2];
   char *p;
   int i;

   p = (char*)buf;
   memcpy(k, key, 16);

   for(i = len / 8; i > 0; i--){
      memcpy(v, p, 8);
      TeaDecrypt64Bits(v, k);
      memcpy(p, v, 8);
      p += 8;
   }
}

#pragma package(smart_init)
